package com.siun.dk.module;

import android.annotation.SuppressLint;
import android.os.CountDownTimer;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import com.aw.baselib.base.AwBaseBindingActivity;
import com.aw.baselib.base.AwBaseEvent;
import com.aw.baselib.util.AwConvertUtil;
import com.aw.baselib.util.AwDataUtil;
import com.sirun.ble.utils.AwLog;
import com.siun.dk.bean.CalibrationItemBean;
import com.siun.dk.events.EventRefreshBleStatusType;
import com.siun.dk.events.EventRefreshRssiType;
import com.siun.dk.util.BleCalculatorUtil;
import com.siun.wuling.R;
import com.siun.wuling.databinding.ActivityCalibrationBinding;

import java.util.ArrayList;
import java.util.List;

public class CalibrationActivity extends AwBaseBindingActivity<ActivityCalibrationBinding> {

    private static final int DEFALUT_COUNTDOWN_TIME = 30000;
//    private static final int DEFALUT_COUNTDOWN_TIME = 2000;
    private int calCount = 0;
    private boolean isAllowCal = false;
    private double totalRssi = 0;
    private MyCountTime mCountTime;
    private TextView mCurrentTvRssi, mCurrentToCalEveryDistance;
    private double mCurrentCalRssi = 0;
    private int mCurrentCalDistance = 1;
    private List<CalibrationItemBean> mCalList = new ArrayList<>();

    @Override
    public void refreshByBus(AwBaseEvent type) {
        super.refreshByBus(type);
        if(type instanceof EventRefreshRssiType) {
            if(isAllowCal) {
                calCount++;
                totalRssi += ((int)type.getObj());
                AwLog.d("Calibration refreshByBus totalRssi: " + totalRssi + " ,calCount: " + calCount);
            }
        } else if(type instanceof EventRefreshBleStatusType) {
            boolean isConnect = (boolean) type.getObj();
            if(isConnect) {
                dismissDialog();
            } else {
                showDialog("蓝牙连接失败，请重新连接", v -> finish());
            }
        }
    }

    @Override
    protected ActivityCalibrationBinding getViewBinding() {
        return ActivityCalibrationBinding.inflate(getLayoutInflater());
    }

    @Override
    protected void initView() {
        super.initView();
        setToolbar("蓝牙标定", null);
    }

    @Override
    protected void initData() {
        super.initData();
        BleCalculatorUtil.main();
    }

    @SuppressLint("MissingInflatedId")
    @Override
    protected void initListener() {
        super.initListener();
        binding.tvToCal1mDistance.setOnClickListener(v -> {
            mCurrentCalDistance = 1;
            mCurrentTvRssi = binding.tv1mDistanceResult;
            mCurrentToCalEveryDistance = binding.tvToCal1mDistance;
            startCountDown();
        });
        binding.tvAddDynamics.setOnClickListener(v -> {
            if(mCurrentCalRssi == 0) {
                showMsg("请先完成1米标定");
                return;
            }
            if(mCalList.size() < (binding.llDynamicsCalibrationLayout.getChildCount() + 1)) {
                showMsg("请先记录未完成标定");
                return;
            }
            View view = LayoutInflater.from(mActivity).inflate(R.layout.view_dynamics_calibration, null);
            EditText et_distance = view.findViewById(R.id.et_distance);
            TextView tv_rssi = view.findViewById(R.id.tv_rssi);
            TextView tv_toCalEveryDistance = view.findViewById(R.id.tv_toCalEveryDistance);
            tv_toCalEveryDistance.setOnClickListener(v1 -> {
                if(AwDataUtil.isEmpty(getText(et_distance))) {
                    showMsg("请输入整数距离");
                    return;
                }
                if(!getText(tv_toCalEveryDistance).contains("重新记录")) {
                    if(isCalibrationFinish(Integer.parseInt(getText(et_distance)))) {
                        showMsg("该距离标定已存在");
                        return;
                    }
                }
                mCurrentTvRssi = tv_rssi;
                mCurrentToCalEveryDistance = tv_toCalEveryDistance;
                mCurrentCalDistance = Integer.parseInt(getText(et_distance));
                startCountDown();

            });
            binding.llDynamicsCalibrationLayout.addView(view);
        });
        binding.tvToCalN.setOnClickListener(v -> {
            if(mCalList.size() < 3) {
                showMsg("请先标定至少3个距离数据");
                return;
            }
            double[][] measurements = new double[mCalList.size()][];
            for(int i=0; i<mCalList.size(); i++) {
                CalibrationItemBean itemBean = mCalList.get(i);
                //以下是调试用假数据
//                double rssi = 0;
//                switch (i) {
//                    case 0:
//                        rssi = -50.0;
//                        break;
//                    case 1:
//                        rssi = -60.0;
//                        break;
//                    case 2:
//                        rssi = -65.0;
//                        break;
//                    case 3:
//                        rssi = -70.0;
//                        break;
//                }
//                measurements[i] = new double[]{itemBean.getDistance(), rssi, itemBean.getWeight()};
                measurements[i] = new double[]{itemBean.getDistance(), itemBean.getRssi(), itemBean.getWeight()};

            }
            double[] result = BleCalculatorUtil.estimatePathLossParams(measurements);
            AwLog.d("Calibration 环境因子计算结果A: " + result[0] + " ,N: " + result[1]);
            setText(binding.tvCalNResult, "环境因子计算结果：" +  result[1]);
        });
    }

    private boolean isCalibrationFinish(double distance) {
        if(AwDataUtil.isEmpty(mCalList)) {
            return false;
        }
        boolean isExist = false;
        for(CalibrationItemBean itemBean : mCalList) {
            if(itemBean.getDistance() == distance) {
                isExist = true;
                break;
            }
        }
        return isExist;
    }

    private void replaceSubItemRssi(int distance, double rssi) {
        if(AwDataUtil.isEmpty(mCalList)) {
            return;
        }
        for(CalibrationItemBean itemBean : mCalList) {
            if(itemBean.getDistance() == distance) {
                itemBean.setRssi(rssi);
            }
        }
    }

    private void printList() {
        if(AwDataUtil.isEmpty(mCalList)) {
            return;
        }
        for(int i=0; i<mCalList.size(); i++) {
            CalibrationItemBean itemBean = mCalList.get(i);
            AwLog.d("Calibration printList, i: " + i + " ,item: " + itemBean.toString());
        }
    }

    public class MyCountTime extends CountDownTimer {

        public MyCountTime(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
        }

        @Override
        public void onFinish() {
            isAllowCal = false;
            if(mCurrentTvRssi != null) {
                mCurrentCalRssi = -AwConvertUtil.div(totalRssi, calCount, 2);
                AwLog.d("Calibration CountDownTimer onFinish totalRssi: " + totalRssi + " ,calCount: " + calCount + " ,计算结果RSSI: " + mCurrentCalRssi);
                if(mCurrentTvRssi == binding.tv1mDistanceResult) {
                    mCurrentTvRssi.setText("1米标定（" + mCurrentCalRssi + "）");
                    if(isCalibrationFinish(mCurrentCalDistance)) {
                        replaceSubItemRssi(mCurrentCalDistance, mCurrentCalRssi);
                    } else {
                        mCalList.add(new CalibrationItemBean(mCurrentCalDistance, mCurrentCalRssi, getCalWeight(1)));
                    }
                } else {
                    mCurrentTvRssi.setText(mCurrentCalRssi + "");
                    if(isCalibrationFinish(mCurrentCalDistance)) {
                        replaceSubItemRssi(mCurrentCalDistance, mCurrentCalRssi);
                    } else {
                        mCalList.add(new CalibrationItemBean(mCurrentCalDistance, mCurrentCalRssi, getCalWeight(mCurrentCalDistance)));
                    }
                }
                mCurrentToCalEveryDistance.setText("重新记录");
                printList();
            }
            cancelCountdown();
        }

        @Override
        public void onTick(long millisUntilFinished) {
        }
    }

    private void startCountDown() {
        AwLog.d(TAG, "Calibration startCountDown", "...");
        if(mCountTime == null) {
            mCountTime = new MyCountTime(DEFALUT_COUNTDOWN_TIME, 1000);
        }
        showLoadingDialog();
        mCountTime.start();
        calCount = 0;
        totalRssi = 0;
        isAllowCal = true;
    }

    private void cancelCountdown() {
        AwLog.d(TAG, "Calibration cancelCountdown", "...");
        if(mCountTime != null) {
            mCountTime.cancel();
            mCountTime = null;
            calCount = 0;
            isAllowCal = false;
        }
        dismissLoadingDialog();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        cancelCountdown();
    }

    private double getCalWeight(int distance) {
        switch (distance) {
            case 1:
                return 1.0;
            case 2:
                return 0.7;
            case 3:
                return 0.5;
            case 4:
                return 0.3;
            case 5:
                return 0.2;
            default:
                return 1.0;
        }
    }
}
